using System;
using NUnit.Framework;

namespace ValidationFramework.Tests
{
    [TestFixture]
    public class RequiredNumberRuleAttributeTest
    {


        [Test]
        public void RunForAllNumberTypes()
        {
            CallAttributeTester<byte>();
            CallAttributeTester<int>();
            CallAttributeTester<long>();
            CallAttributeTester<double>();
            CallAttributeTester<float>();
            CallAttributeTester<short>();
            CheckDefaultValues<byte>();
            CheckDefaultValues<int>();
            CheckDefaultValues<long>();
            CheckDefaultValues<double>();
            CheckDefaultValues<float>();
            CheckDefaultValues<short>();
            CheckNonDefaultValues<byte>();
            CheckNonDefaultValues<int>();
            CheckNonDefaultValues<long>();
            CheckNonDefaultValues<double>();
            CheckNonDefaultValues<float>();
            CheckNonDefaultValues<short>();
        }

        public void CheckDefaultValues<T>()
        {
            var ruleAttribute = GetRuleAttribute<T>();
            Assert.IsNull(ruleAttribute.ErrorMessage);

            var propertyRule = TypeHelper.CreatePropertyRule<RequiredRule<T>>(ruleAttribute, new MockPropertyDescriptor<T>("foo"));
            var parameterRule = TypeHelper.CreateParameterRule<RequiredRule<T>>(ruleAttribute, new MockParameterDescriptor<T>("foo"));

            Assert.IsFalse(propertyRule.HasInitialValue);
            Assert.IsFalse(parameterRule.HasInitialValue);
        }

        private static RuleAttribute GetRuleAttribute<T>()
        {
            var attributeTypeName = string.Format("ValidationFramework.Required{0}RuleAttribute,ValidationFramework", TypeHelper.GetTypeFromKeyName<T>());
            var attributeType = Type.GetType(attributeTypeName);
            return (RuleAttribute)Activator.CreateInstance(attributeType);
        }


        public void CheckNonDefaultValues<T>()
        {
            var ruleAttribute = GetRuleAttribute<T>();
            const byte expectedInitialValue = 3;
            TypeHelper.SetPropertyValue(ruleAttribute, "InitialValue", expectedInitialValue);
            Assert.AreEqual(expectedInitialValue, TypeHelper.GetPropertyValue<T>(ruleAttribute, "InitialValue"));

            var propertyRule = TypeHelper.CreatePropertyRule<RequiredRule<T>>(ruleAttribute, new MockPropertyDescriptor<T>("foo"));
            var parameterRule = TypeHelper.CreateParameterRule<RequiredRule<T>>(ruleAttribute, new MockParameterDescriptor<T>("foo"));

            Assert.AreEqual(expectedInitialValue, propertyRule.InitialValue);
            Assert.AreEqual(expectedInitialValue, parameterRule.InitialValue);
        }

        public void CallAttributeTester<T>() 
        {
            AttributeTester.CheckDefaultValues<T>(GetRuleAttribute<T>(), true, true);
            AttributeTester.CheckNonDefaultValues<T>(GetRuleAttribute<T>(), true, true);
        }


    }
}